package com.xb.loan.util.ftp;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import com.xb.loan.util.StringUtils;
import com.xb.loan.util.log.DefaultLoggerFacotry;
import com.xb.loan.util.log.LogFormatUtil;
import org.slf4j.Logger;

import com.enterprisedt.net.ftp.FTPConnectMode;
import com.enterprisedt.net.ftp.FTPException;
import com.enterprisedt.net.ftp.FTPFile;
import com.enterprisedt.net.ftp.FileTransferClient;
import com.enterprisedt.net.ftp.WriteMode;

/** 从ftp下载文件到本地 */
public class FtpUtil {

    private Logger log = DefaultLoggerFacotry.getLogger(FtpUtil.class);

    /**
     * 登录ftp用户名
     */
    private String username = null;

    /**
     * 登录密码
     */
    private String password = null;

    /**
     * ftp服务器ip
     */
    private String host = null;

    /**
     * ftp服务器端口
     */
    private int port = 21;

    /**
     * 超时时间
     */
    private int timeout = 2000;

    /**
     * 是否主动连接模式
     * */
    private boolean activeMode = false;   
    
    public FtpUtil() {
        super();
    }

    public FtpUtil(String username, String password, String host, int port) {
        super();
        this.username = username;
        this.password = password;
        this.host = host;
        this.port = port;
    }
    /**
     * 
     * 上传文件
     * @param localFilePath
     * @param remoteFilePath
     * @return
     * 2015年10月14日 by ziqiang.zhang
     */
    public boolean upload(String localFilePath,String remoteFilePath){
        
        FileTransferClient ftp = null;

        try {
            // 获取连接
            ftp = connect();
            
            log.info(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","message"}),new Object[]{localFilePath,remoteFilePath,"upload file start"});
            
            // 上传文件
            ftp.uploadFile(localFilePath, remoteFilePath);
            
            log.info(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","message"}),new Object[]{localFilePath,remoteFilePath,"upload file success"});           
            
            return true;

        } catch (Exception e) {

            log.info(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","message"}),new Object[]{localFilePath,remoteFilePath,"upload have an exception"});
            
            e.printStackTrace();
            if(ftp != null && ftp.isConnected()){
                ftp.cancelAllTransfers();
            }
            
            return false;

        } finally {
            if (ftp != null && ftp.isConnected()) {
                try {

                    ftp.disconnect();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    /**
     * 创建指定文件夹上传文件
     * @param localFilePath
     * @param remoteDir
     * @param remoteFileName
     * @return
     * 2015-10-14 by zhaolijun
     */
    public boolean upload(String localFilePath, String remoteDir, String remoteFileName) {
        FileTransferClient ftp = null;

        String remoteFilePath = null;
        
        boolean isExists = false;
        
        try {
            // 获取连接
            ftp = connect();
            
            remoteFilePath = remoteDir+"/"+remoteFileName;
            
             if (!StringUtils.isEmpty(remoteDir)) {
                FTPFile[] ftpFile = ftp.directoryList();
                for (FTPFile ff : ftpFile) {
                    if (ff.getName().equals(remoteDir)) {
                        isExists = true;
                        break;
                    }
                }
                if (isExists) {
                    ftp.changeDirectory(remoteDir);//切换目录
                } else {
                    ftp.createDirectory(remoteDir);
                    ftp.changeDirectory(remoteDir);//切换目录
                }
            }
            
            log.info(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","message"}),new Object[]{localFilePath,remoteFilePath,"upload file start"});
            
            // 上传文件
            ftp.uploadFile(localFilePath, remoteFileName);
            
            log.info(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","message"}),new Object[]{localFilePath,remoteFilePath,"upload file success"});           
            
            return true;

        } catch (Exception e) {

            log.error(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","message"}),new Object[]{localFilePath,remoteFilePath,"upload have an exception"});
            
            e.printStackTrace();
            if(ftp != null && ftp.isConnected()){
                ftp.cancelAllTransfers();
            }
            
            return false;

        } finally {
            if (ftp != null && ftp.isConnected()) {
                try {

                    ftp.disconnect();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public boolean uploadFileBySftp(File localFile,String remoteUpPath) {

    	SftpUtil sftpUtil = new SftpUtil(host,port,username,password,timeout);
    	String localFileDir = localFile.getParentFile().getAbsolutePath();
    	String remoteFileDir = remoteUpPath;
    	String fileName = localFile.getName();
    	return sftpUtil.uploadFile(localFileDir, remoteFileDir, fileName);
    }
    
    public boolean uploadFile(File localFile,String remoteUpPath) {

        FileTransferClient ftp = null;
        try {

            ftp = this.connect();
            ftp.changeDirectory(remoteUpPath);
            // 如果存在改文件则删除
            if (ftp.exists(localFile.getName())) {
                ftp.deleteFile(localFile.getName());
            }
            
            // 直接上传
            String result = ftp.uploadFile(localFile.getAbsolutePath(), localFile.getName(),WriteMode.RESUME);
            log.info(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","message"}),new Object[]{localFile,remoteUpPath,result});
        } catch (Exception e) {
            e.printStackTrace();
            if (ftp != null && ftp.isConnected()) {
                ftp.cancelAllTransfers();
            }
            return false;
        } finally {
            if (ftp != null && ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        return true;
    }
    
    /**
     * @param remoteFilePath
     * @param localFilePath
     * @return
     */
    public boolean downloadBySftp(String remoteFilePath, String localFilePath) {
    	
    	SftpUtil sftpUtil = new SftpUtil(host,port,username,password,timeout);
    	//远程系统文件分隔符
    	String remoteFileSeparator = "/";
    	if(!remoteFilePath.contains("/")){
    		remoteFileSeparator = "\\";
    	}
    	String localFileDir = localFilePath.substring(0,localFilePath.lastIndexOf(File.separator)+1);
    	String remoteFileDir = remoteFilePath.substring(0,remoteFilePath.lastIndexOf(remoteFileSeparator)+1);
    	String fileName = localFilePath.substring(localFilePath.lastIndexOf(File.separator)+1);
    	return sftpUtil.downloadFile(remoteFileDir, localFileDir, fileName);
    }
    
    /**
     * 下载文件，首先生成临时文件，下载完毕后改名
     * */
    public boolean download(String remoteFilePath, String localFilePath) {

        File tempFile = new File(localFilePath + ".temp");

        boolean result = download1(tempFile.getAbsolutePath(), remoteFilePath);
        // 下载成功
        if (result) {
            try {

                result = tempFile.renameTo(new File(localFilePath));

            } catch (Exception e) {

                e.printStackTrace();
            }

            return result;

        } else {
            // 删除临时文件
            if (tempFile.exists()) {
                try {

                    tempFile.delete();

                } catch (Exception e) {
                    e.printStackTrace();                           
                }
            }
        }

        return false;

    }

    /**
     * 通过本地路径和远程路径 从ftp上下载文件到本地
     * 
     * @param localFilePath
     *            日志消息id
     * @return 返回true 成功
     * 
     */
    private boolean download1(String localFilePath, String remoteFilePath) {

        FileTransferClient ftp = null;

        try {
            // 获取连接
            ftp = connect();
            // 下载文件
            boolean result = downloadIfExist(localFilePath, remoteFilePath, ftp);

            return result;

        } catch (Exception e) {

            log.info(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","message"}),new Object[]{localFilePath,remoteFilePath,e.getMessage()});
            
            e.printStackTrace();
            
            if (ftp != null && ftp.isConnected()) {
                ftp.cancelAllTransfers();
            }

            return false;

        } finally {
            if (ftp != null && ftp.isConnected()) {
                try {

                    ftp.disconnect();
                    
                    log.info(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","message"}),new Object[]{localFilePath,remoteFilePath,"close ftp connection sucess!"});
                                    
                } catch (Exception e) {

                    log.error(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","message"}),new Object[]{localFilePath,remoteFilePath,"close have an exception"});                             
                    
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 建立连接
     * 
     * @throws IOException
     * @throws FTPException
     */
    private FileTransferClient connect() throws FTPException, IOException {

        FileTransferClient ftp = new FileTransferClient();

        ftp = new FileTransferClient();
        // set remote host
        ftp.setRemoteHost(host);
        // set username
        ftp.setUserName(username);
        // set password
        ftp.setPassword(password);
        // set port
        ftp.setRemotePort(port);
        // set timeout
        ftp.setTimeout(timeout);
        // 设置连接模式
        ftp.getAdvancedFTPSettings().setConnectMode(activeMode ? FTPConnectMode.ACTIVE : FTPConnectMode.PASV);
        // 日志
        log.info("start to connect to ftp server....");
               
        ftp.connect();
        log.info("connect to ftp server successfull....");
        
        return ftp;

    }

    /**
     *
     * @param localFilePath
     * @param remoteFilePath
     * @param ftp
     * @return true ftp服务器上有该文件，并且下载成功
     * @throws FTPException
     * @throws IOException
     */
    private boolean downloadIfExist(String localFilePath, String remoteFilePath, FileTransferClient ftp) throws FTPException, IOException {

        if (!isExist(remoteFilePath, ftp)) {

            return false;
        }
        // 看文件夹是否存在，不存在则创建
        File file = new File(localFilePath);

        File parent = file.getParentFile();

        if (!parent.exists()) {

            parent.mkdirs();

        }

        // 下载文件
        ftp.downloadFile(localFilePath, remoteFilePath);
        //下载完毕后核对本地文件和服务器上文件大小，如果大小不相同,继续下载
        long downloadsize = new File(localFilePath).length();
        long ftpsize = ftp.getSize(remoteFilePath);

        if (downloadsize != ftpsize) {
            
            log.info(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","downloadsize","ftpsize","message"}),new Object[]{localFilePath,remoteFilePath,downloadsize,ftpsize,"download file from ftp server failure!"});
            
            return downloadIfExist(localFilePath, remoteFilePath, ftp);
        }
        log.info(LogFormatUtil.getFormatTemplate(new String[]{"localFilePath","remoteFilePath","downloadsize","message"}),new Object[]{localFilePath,remoteFilePath,downloadsize,"download file from ftp server successfull!"});
        
        return true;
    }

    private boolean isExist(String remoteFilePath, FileTransferClient ftp) throws FTPException, IOException {

        boolean isExist = ftp.exists(remoteFilePath);

        if (!isExist) {
            
            log.info(LogFormatUtil.getFormatTemplate(new String[]{"remoteFilePath","message"}),new Object[]{remoteFilePath,"remote file does not exits!"});                      
        }

        return isExist;
    }

    public byte[] downloadByteArray(String remoteFilePath) {

        FileTransferClient ftp = null;

        try {
            // 获取连接
            ftp = connect();
            // 下载文件
            if (!isExist(remoteFilePath, ftp)) {

                return null;
            }

            byte[] data = ftp.downloadByteArray(remoteFilePath);
            
            log.info(LogFormatUtil.getFormatTemplate(new String[]{"remoteFilePath","message"}),new Object[]{remoteFilePath,"get byteArray success,size:" + data.length});                      
            
            return data;

        } catch (Exception e) {
            
            log.info(LogFormatUtil.getFormatTemplate(new String[]{"remoteFilePath","message"}),new Object[]{remoteFilePath, "down have an exception"});                      
            e.printStackTrace();
            if (ftp != null && ftp.isConnected()) {
                ftp.cancelAllTransfers();
            }

            return null;

        } finally {
            if (ftp != null && ftp.isConnected()) {
                try {

                    ftp.disconnect();
                    
                    log.info(LogFormatUtil.getFormatTemplate(new String[]{"remoteFilePath","message"}),new Object[]{remoteFilePath,"close ftp connection sucess"});                      
                   
                } catch (Exception e) {
                    
                    log.error(LogFormatUtil.getFormatTemplate(new String[]{"remoteFilePath","message"}),new Object[]{remoteFilePath, e});                                         
                }
            }
        }
    }

    public Date getModifyTime(String remoteFilePath) {

        FileTransferClient ftp = null;

        try {
            // 获取连接
            ftp = connect();

            if (!ftp.exists(remoteFilePath)) {

                log.info(LogFormatUtil.getFormatTemplate(new String[]{"remoteFilePath","message"}),new Object[]{remoteFilePath,"file not exists on ftp"});                      
               
                return null;
            }

            return ftp.getModifiedTime(remoteFilePath);

        } catch (Exception e) {

            log.info(LogFormatUtil.getFormatTemplate(new String[]{"remoteFilePath","message"}),new Object[]{remoteFilePath, e.getMessage()});
            
            e.printStackTrace();
            if (ftp != null && ftp.isConnected()) {
                ftp.cancelAllTransfers();
            }

            return null;

        } finally {
            if (ftp != null && ftp.isConnected()) {
                try {

                    ftp.disconnect();
                    
                    log.info(LogFormatUtil.getFormatTemplate(new String[]{"remoteFilePath","message"}),new Object[]{remoteFilePath,"close ftp connection sucess" });
                    
                } catch (Exception e) {
                    log.error(LogFormatUtil.getFormatTemplate(new String[]{"remoteFilePath","message"}),new Object[]{remoteFilePath, e});
                }
            }
        }

    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public boolean isActiveMode() {
        return activeMode;
    }

    public void setActiveMode(boolean activeMode) {
        this.activeMode = activeMode;
    }
    
    public static void main(String[] args) {
        FtpUtil ftpUtil = new FtpUtil("v31","v31","192.168.1.23",21);
        System.out.println(ftpUtil.upload("E:\\platAccount\\charge\\20160118_20160119095753.txt", "platAccountCharge2", "20160118_20160119095753.txt"));
    }

}
